package com.mg.game.content;

import com.mg.framework.tiled.Map;
import com.mg.framework.tiled.TileLayer;
import com.mg.framework.tiled.TileObject;
import com.mg.game.content.gamescreen.GameActor;

public class CollisionDetection {

	private Map map;

	public CollisionDetection(Map map) {
		this.map = map;
	}

	public boolean isOverX(GameActor gameActor) {
		while (Math.abs(gameActor.tmpSpeedX) >= 1) {
			if ((gameActor.tmpSpeedX < 0 && (gameActor.getX() + gameActor.tmpSpeedX) >= 0)
					|| (gameActor.tmpSpeedX > 0 && (gameActor.getX()
							+ gameActor.getWidth() + gameActor.tmpSpeedX) < gameActor
							.getScreen().getGameStageWidth())) {
				return false;
			} else {
				if (Math.abs(gameActor.tmpSpeedX) == 1) {
					return true;
				} else {
					gameActor.tmpSpeedX = Math.signum((gameActor.tmpSpeedX))
							* (Math.abs(gameActor.tmpSpeedX) - 1);
				}
			}
		}
		return false;
	}

	public boolean isOverY(GameActor gameActor) {
		while (Math.abs(gameActor.tmpSpeedY) >= 1) {
			if ((gameActor.tmpSpeedY < 0 && (gameActor.getY() + gameActor.tmpSpeedY) >= 0)
					|| (gameActor.tmpSpeedY > 0 && (gameActor.getY()
							+ gameActor.getHeight() + gameActor.tmpSpeedY) < gameActor
							.getScreen().getGameStageHeight())) {
				return false;
			} else {
				if (Math.abs(gameActor.tmpSpeedY) == 1) {
					return true;
				} else {
					gameActor.tmpSpeedY = Math.signum((gameActor.tmpSpeedY))
							* (Math.abs(gameActor.tmpSpeedY) - 1);
				}
			}
		}
		return false;

	}

	public boolean hitLeft(GameActor gameActor, String mapLayerName, String type) {
		if (gameActor.tmpSpeedX < 0) {
			while (Math.abs(gameActor.tmpSpeedX) >= 1) {
				if (!leftOrRightHasObstruct(gameActor, gameActor.getX()
						+ gameActor.tmpSpeedX, gameActor.getY(),
						gameActor.getHeight(), mapLayerName, type)) {
					return false;
				} else {
					if (Math.abs(gameActor.tmpSpeedX) == 1) {
						return true;
					} else {
						gameActor.tmpSpeedX = Math
								.signum((gameActor.tmpSpeedX))
								* (Math.abs(gameActor.tmpSpeedX) - 1);
					}
				}
			}
		}
		return false;
	}

	public boolean hitRight(GameActor gameActor, String mapLayerName,
			String type) {
		if (gameActor.tmpSpeedX > 0) {
			while (Math.abs(gameActor.tmpSpeedX) >= 1) {
				if (!leftOrRightHasObstruct(gameActor, gameActor.getX()
						+ gameActor.getWidth() + gameActor.tmpSpeedX,
						gameActor.getY(), gameActor.getHeight(), mapLayerName,
						type)) {
					return false;
				} else {
					if (Math.abs(gameActor.tmpSpeedX) == 1) {
						return true;
					} else {
						gameActor.tmpSpeedX = Math
								.signum((gameActor.tmpSpeedX))
								* (Math.abs(gameActor.tmpSpeedX) - 1);
					}
				}
			}
		}
		return false;
	}

	public boolean hitTop(GameActor gameActor, String mapLayerName, String type) {
		if (gameActor.tmpSpeedY < 0) {
			while (Math.abs(gameActor.tmpSpeedY) >= 1) {
				if (!topOrBottomHasObstruct(gameActor, gameActor.getX(),
						gameActor.getY() + gameActor.tmpSpeedY,
						gameActor.getWidth(), mapLayerName, type)) {
					return false;
				} else {
					if (Math.abs(gameActor.tmpSpeedY) == 1) {
						return true;
					} else {
						gameActor.tmpSpeedY = Math
								.signum((gameActor.tmpSpeedY))
								* (Math.abs(gameActor.tmpSpeedY) - 1);
					}
				}
			}
		}

		return false;
	}

	public boolean hitBottom(GameActor gameActor, String mapLayerName,
			String type) {
		if (gameActor.tmpSpeedY > 0) {
			while (Math.abs(gameActor.tmpSpeedY) >= 1) {
				if (!topOrBottomHasObstruct(gameActor, gameActor.getX(),
						gameActor.getY() + gameActor.getHeight()
								+ gameActor.tmpSpeedY, gameActor.getWidth(),
						mapLayerName, type)) {
					return false;
				} else {
					if (Math.abs(gameActor.tmpSpeedY) == 1) {
						return true;
					} else {
						gameActor.tmpSpeedY = Math
								.signum((gameActor.tmpSpeedY))
								* (Math.abs(gameActor.tmpSpeedY) - 1);
					}
				}
			}
		}
		return false;
	}

	private boolean leftOrRightHasObstruct(GameActor gameActor, float x,
			float y, int height, String mapLayerName, String type) {
		TileLayer tileLayer = map.getTileLayerByTileLayerName(mapLayerName);
		return leftOrRightHasObstruct(gameActor, tileLayer,
				(int) (x / map.getTileWidth()),
				(int) (y / map.getTileHeight()),
				(int) ((y + height) / map.getTileHeight()), type);
	}

	private boolean topOrBottomHasObstruct(GameActor gameActor, float x,
			float y, int width, String mapLayerName, String type) {
		TileLayer tileLayer = map.getTileLayerByTileLayerName(mapLayerName);
		return topOrBottomHasObstruct(gameActor, tileLayer,
				(int) (x / map.getTileWidth()),
				(int) ((x + width) / map.getTileWidth()),
				(int) (y / map.getTileHeight()), type);
	}

	public boolean leftOrRightHasObstruct(GameActor gameActor,
			TileLayer tileLayer, int col, int startRow, int endRow, String type) {

		int row = startRow;
		boolean has = false;
		if ("ALL".equals(type)) {
			while (row <= endRow) {
				if (isObstruct(tileLayer.getTileObjects()[row][col])) {
					has = true;
					if (gameActor.getSpeedXAbs() == 1) {

					}
				}
				row++;
			}
		} else {
			while (row <= endRow) {
				if (isObstruct(tileLayer.getTileObjects()[row][col], type)) {
					has = true;
					if (gameActor.getSpeedXAbs() == 1) {

					}
				}
				row++;
			}
		}
		return has;
	}

	public boolean topOrBottomHasObstruct(GameActor gameActor,
			TileLayer tileLayer, int startCol, int endCol, int row, String type) {

		int col = startCol;
		boolean has = false;
		if ("ALL".equals(type)) {
			while (col <= endCol) {
				if (isObstruct(tileLayer.getTileObjects()[row][col])) {
					has = true;
					if (gameActor.getSpeedYAbs() == 1) {

					}
				}
				col++;
			}
		} else {
			while (col <= endCol) {
				if (isObstruct(tileLayer.getTileObjects()[row][col], type)) {
					has = true;
					if (gameActor.getSpeedYAbs() == 1) {

					}
				}
				col++;
			}
		}
		return has;
	}

	private boolean isObstruct(TileObject tileObject) {
		if (tileObject != null) {
			return true;
		}
		return false;
	}

	private boolean isObstruct(TileObject tileObject, String type) {
		if (tileObject != null && tileObject.isMe(type)) {
			return true;
		}
		return false;
	}
}
